function compose(middleware) {
  console.log(" middleware:", middleware.length);
  // 输入：middleware 是一个函数数组，每个元素都是一个中间件函数
  // 输出：一个新的中间件函数
  return function (ctx, next) {
    let index = -1;
    return dispatch(0);

    function dispatch(i) {
      // 检查是否多次调用同一中间件
      if (i <= index)
        return Promise.reject(new Error("next() called multiple times"));

      index = i;

      let fn = middleware[i];

      // 最后一个中间件后面的函数是传入的 next
      if (i === middleware.length) fn = next;

      if (!fn) return Promise.resolve();

      // 递归调用，实现洋葱模型的效果
      try {
        return Promise.resolve(
          fn(ctx, function next() {
            return dispatch(i + 1);
          })
        );
      } catch (err) {
        return Promise.reject(err);
      }
    }
  };
}

const m1 = async (ctx, next) => {
  console.log("🚀～ ctx:", ctx);
  console.log("m1");
  await next(); // 调用下一个中间件
  console.log("m1 e");
};

const m2 = async (ctx, next) => {
  console.log("m2 s");
  await next(); // 调用下一个中间件
  console.log("m2 e");
};

// compose([m1, m2])("hha");

// express
// function c(middleware) {
//   return function (ctx, next) {
//     let i = -1;
//     return dispatch(0);

//     function dispatch(i) {}
//   };
// }

function mc(midd) {
  return function (ctx, next) {
    let index = -1;
    dispatch(0);

    function dispatch(i) {
      if (i <= index)
        return Promise.reject(new Error("next() called multiple times"));
      index = i;

      const fn = midd[i];

      if (i === middleware.length) fn = next;

      if (!fn) return Promise.resolve();

      return Promise.resolve(
        fn(ctx, function () {
          return dispatch(i + 1);
        })
      );
    }
  };
}

// function crduce(middleware = []) {
//   return function (ctx) {
//     return middleware.reduceRight((next, middle));
//   };
// }

// const crduce = (middle) => (ctx) =>
//   middle.reverse().reduce((next, mid) => {
//     Promise.resolve(mid(ctx, next));
//   }, Promise.resolve());

// function crduce(middlewares) {
//   return function (ctx, ne) {
//     // 初始值，即最后的一个函数，它只要处理掉当前的 promise，然后返回，不再调用 next
//     const endFn = Promise.resolve();

//     if (!ne) return Promise.resolve();

//     // reduceRight 从右向左运行，因此实现了洋葱模型的效果
//     return middlewares.reduceRight((next, middleware) => {
//       return () => Promise.resolve(middleware(ctx, next));
//     }, endFn)(); // 调用返回的函数得到结果
//   };
// }

// crduce([m1, m2])("123");
